const express = require("express");
const { Client } = require("@notionhq/client");
require("dotenv").config();

const app = express();

//const port = 3001;

app.get("/", (req, res) => {
  res.send("Hello World!");
});

// app.listen(port, () => {
//   console.log(`Example app listening at http://localhost:${port}/comments`);
// });

const NOTION_KEY = process.env.NOTION_KEY;
const NOTION_DB_ID = process.env.NOTION_DB_ID;
const NOTION_CURR_USER_ID = process.env.NOTION_CURR_USER_ID;

const notion = new Client({ auth: NOTION_KEY });

app.use(express.json());

// 获取notion-page数据，并简化
async function getAllComments() {
  const result = await notion.databases.query({ database_id: NOTION_DB_ID });
  const comments = new Map();
  // 原始评论数据
  result?.results?.forEach((page) => {
    comments.set(page.id, transformPageObject(page));
  });

  // 组装回复，把关系 id 替换为实际评论
  let commentsPopulated = [...comments.values()].reduce((acc, curr) => {
    if (!curr.replyTo) {
      curr.replies = curr.replies.map((reply) => comments.get(reply.id));
      acc.push(curr);
    }
    return acc;
  }, []);

  return commentsPopulated;
}

// 相对时间转换
function getRelativeTimeDesc(time) {
  const currentInMs = new Date().getTime();
  const timeInMs = new Date(time).getTime();

  const minuteInMs = 60 * 1000;
  const hourInMs = 60 * minuteInMs;
  const dayInMs = 24 * hourInMs;
  const monthInMs = 30 * dayInMs;
  const yearInMs = 365 * dayInMs;

  const relativeTime = currentInMs - timeInMs;
  if (relativeTime < minuteInMs) {
    return `${Math.ceil(relativeTime / 1000)} 秒前`;
  } else if (relativeTime < hourInMs) {
    return `${Math.ceil(relativeTime / minuteInMs)} 分钟前`;
  } else if (relativeTime < dayInMs) {
    return `${Math.ceil(relativeTime / hourInMs)} 小时前`;
  } else if (relativeTime < monthInMs) {
    return `${Math.ceil(relativeTime / dayInMs)} 天前`;
  } else if (relativeTime < yearInMs) {
    return `${Math.ceil(relativeTime / monthInMs)} 月前`;
  } else {
    return `${Math.ceil(relativeTime / yearInMs)} 年前`;
  }
}

// 提交留言
async function addComment({ content, replyTo = "" }) {
  // 获取no：总留言数量+1
  let no =
    (await notion.databases.query({ database_id: NOTION_DB_ID })).results
      .length + 1;

  // 获取avatar和name：根据notion中的用户信息
  let { avatar_url, name } = await notion.users.retrieve({
    user_id: NOTION_CURR_USER_ID,
  });

  // 发送post请求：添加数据
  const page = await notion.request({
    method: "POST",
    path: "pages",
    body: {
      parent: { database_id: NOTION_DB_ID },
      properties: {
        no: {
          title: [
            {
              text: {
                content: no.toString(),
              },
            },
          ],
        },
        user: {
          rich_text: [
            {
              text: {
                content: name,
              },
            },
          ],
        },
        avatar: {
          url: avatar_url,
        },
        content: {
          rich_text: [
            {
              text: {
                content,
              },
            },
          ],
        },
        // 如果有 replyTO 参数传递进来的，再添加到请求 body 中
        ...(replyTo && {
          replyTo: {
            relation: [
              {
                id: replyTo,
              },
            ],
          },
        }),
      },
    },
  });
  // 发送完后，接收转化，以便自动更新
  return transformPageObject(page);
}

// 简化page为可用的comments
function transformPageObject(page) {
  return {
    id: page.id,
    user: page.properties.user.rich_text[0].text.content,
    time: getRelativeTimeDesc(page.properties.time.created_time),
    content: page.properties.content.rich_text[0].text.content,
    avatar: page.properties.avatar.url,
    replies: page.properties.replies.relation,
    replyTo: page.properties.replyTo?.relation[0]?.id,
  };
}

/* 
使用 app.get 创建一个处理 get 请求的函数，处理 /comments 路径，
在里边调用 getAllComments() 获取评论列表，
然后使用 res.json() 把它发送给客户端，再利用 try catch 处理错误信息，
如果有问题，就返回 500 错误码给客户端。
 */
app.get("/api/comments", async (req, res) => {
  try {
    const comments = await getAllComments();
    res.json(comments);
  } catch (error) {
    console.log(error);
    res.sendStatus(500);
  }
});

/* 使用 app.post() 创建一个处理 POST 请求的函数，
路径为 /comments，在里边调用 addComment()，
接收新添加的留言对象并返回给客户端，
如果成功返回 201 状态码，有问题返回 500 状态码： */
app.post("/api/comments", async (req, res) => {
  try {
    const newPage = await addComment(req.body);
    res.status(201).json(newPage);
  } catch (error) {
    console.log(error);
    res.sendStatus(500);
  }
});

// 导出express实例
module.exports = app;
